/**
 * @file    huawei_rs485.c
 * @brief   逆变器协议-华为-RS485协议
 * @author  Liuwei
 * @version 1.0.1
 * @date    2024-06-14
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2024-06-14 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "huawei_rs485.h"
#include "modbus_app.h"
#include "if_di.h"
#include "cfg_prj.h"
#include "sample.h"
#include "parallel_com.h"
#include "var_mng.h"
#include "param_mng.h"
#include "boot_param.h"
#include "If_rtc.h"
/* macro/define --------------------------------------------------------------*/
#define IN1_REG_ST       (0x00)
#define IN1_REG_END      (0x60)  // 多+1防止溢出
#define IN1_REG_SIZE     (IN1_REG_END - IN1_REG_ST + 1)
#define IN2_REG_ST       (0x101)
#define IN2_REG_END      (0x12F) // 多+1防止溢出
#define IN2_REG_SIZE     (IN2_REG_END - IN2_REG_ST + 1)
#define IN3_REG_ST       (0x200)
#define IN3_REG_END      (0x20F) // 多+1防止溢出
#define IN3_REG_SIZE     (IN3_REG_END - IN3_REG_ST + 1)

#define IN4_REG_ST       (0x332)
#define IN4_REG_END      (0x34F) // 多+1防止溢出
#define IN4_REG_SIZE     (IN4_REG_END - IN4_REG_ST + 1)
#define IN5_REG_ST       (0x1000)
#define IN5_REG_END      (0x1150) // 多+1防止溢出
#define IN5_REG_SIZE     (IN5_REG_END - IN5_REG_ST + 1)
#define IN6_REG_ST       (0x3000)
#define IN6_REG_END      (0x300A) // 多+1防止溢出
#define IN6_REG_SIZE     (IN6_REG_END - IN6_REG_ST + 1)
#define IN7_REG_ST       (0x1100)
#define IN7_REG_END      (0x1110) // 多+1防止溢出
#define IN7_REG_SIZE     (IN7_REG_END - IN7_REG_ST + 1)

#define CMD_READ_IN_REG        (0x03)
#define CMD_WRITE_HOLD_REG     (0x10)

#define BMS_ADDR               (0xD6)
/* typedef -------------------------------------------------------------------*/

/* local functions -----------------------------------------------------------*/
static void huawei_read_input_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
static void huawei_update_in1_reg(void);
static void huawei_update_in2_reg(void);
static void huawei_update_in3_reg(void);
static void huawei_update_in4_reg(void);
static void huawei_update_in5_reg(void);
static void huawei_update_in6_reg(void);
static void huawei_update_in7_reg(void);
static uint16_t huawei_write_reg(md_data_type msg);
static void huawei_read_hold_reg_reply(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
/* static variables ----------------------------------------------------------*/
static uint16_t input_reg1_buf[IN1_REG_SIZE] = {0};
static uint16_t input_reg2_buf[IN2_REG_SIZE] = {0};
static uint16_t input_reg3_buf[IN3_REG_SIZE] = {0};
static uint16_t input_reg4_buf[IN4_REG_SIZE] = {0};
static uint16_t input_reg5_buf[IN5_REG_SIZE] = {0};
static uint16_t input_reg6_buf[IN6_REG_SIZE] = {0};
static uint16_t input_reg7_buf[IN7_REG_SIZE] = {0};
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
uint8_t huawei_rs485_analysis(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *tx_buf , uint16_t *tx_len)
{
    md_data_type recv_md_data = {0};
    if(TRUE == modbus_rtu_analysis(rx_buf , rx_len , &recv_md_data))
    {
        if(recv_md_data.addr == BMS_ADDR)
        {
            if(CMD_READ_IN_REG == recv_md_data.cmd_code)
            {
                if((recv_md_data.reg_addr >= IN1_REG_ST)
                 && (recv_md_data.reg_addr + recv_md_data.data_len <= IN1_REG_END + 1))
                {
                    huawei_update_in1_reg();
					huawei_read_input_reg(recv_md_data , tx_buf , tx_len);
					return TRUE;
                }
                else if((recv_md_data.reg_addr >= IN2_REG_ST)
                 && (recv_md_data.reg_addr + recv_md_data.data_len <= IN2_REG_END + 1))
                {
                    huawei_update_in2_reg();
					huawei_read_input_reg(recv_md_data , tx_buf , tx_len );
					return TRUE;
                }
				else if((recv_md_data.reg_addr >= IN3_REG_ST)
                 && (recv_md_data.reg_addr + recv_md_data.data_len <= IN3_REG_END + 1))
                {
                    huawei_update_in3_reg();
					huawei_read_input_reg(recv_md_data , tx_buf , tx_len);
					return TRUE;
                }
				else if((recv_md_data.reg_addr >= IN4_REG_ST)
                 && (recv_md_data.reg_addr + recv_md_data.data_len <= IN4_REG_END + 1))
                {
                    huawei_update_in4_reg();
					huawei_read_input_reg(recv_md_data , tx_buf , tx_len);
					return TRUE;
                }				
				else if((recv_md_data.reg_addr >= IN5_REG_ST)
                 && (recv_md_data.reg_addr + recv_md_data.data_len <= IN5_REG_END + 1))
                {
                    huawei_update_in5_reg();
					huawei_read_input_reg(recv_md_data , tx_buf , tx_len);
					return TRUE;
                }
				else if((recv_md_data.reg_addr >= IN6_REG_ST)
                 && (recv_md_data.reg_addr + recv_md_data.data_len <= IN6_REG_END + 1))
                {
                    huawei_update_in6_reg();
					huawei_read_input_reg(recv_md_data , tx_buf , tx_len);
					return TRUE;
                }
				else if((recv_md_data.reg_addr >= IN7_REG_ST)
                 && (recv_md_data.reg_addr + recv_md_data.data_len <= IN7_REG_END + 1))
                {
                    huawei_update_in7_reg();
					huawei_read_input_reg(recv_md_data , tx_buf , tx_len);
					return TRUE;
                }
                else
                {
                    return FALSE;
                }
            }
			else if(CMD_WRITE_HOLD_REG == recv_md_data.cmd_code)
            {
				if((recv_md_data.reg_addr >= IN4_REG_ST)
					&& (recv_md_data.reg_addr + recv_md_data.data_len <= IN4_REG_END + 1))
				{
					huawei_write_reg(recv_md_data);
					huawei_read_hold_reg_reply(recv_md_data , tx_buf , tx_len);
					return TRUE;
				}
			}
            return FALSE;
        }
        return FALSE;
    }
    return FALSE;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void huawei_read_input_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len)
{
    uint16_t data_len = 0;
    uint16_t crc_code = 0;
    uint8_t i = 0;
    uint8_t *p_tx = tx_buf;
	uint16_t idx_cnt = 0;
	uint16_t *p_reg = 0;
	uint16_t start_addr = 0;

    p_tx[idx_cnt ++] = md_data_msg.addr;
    p_tx[idx_cnt ++] = md_data_msg.cmd_code;
    data_len = md_data_msg.data_len * 2;
    p_tx[idx_cnt ++] = data_len; 
    
	if((md_data_msg.reg_addr >= IN1_REG_ST)
      && (md_data_msg.reg_addr + md_data_msg.data_len <= IN1_REG_END))
	{
		p_reg = input_reg1_buf;
		start_addr = md_data_msg.reg_addr - IN1_REG_ST;
	}
	if((md_data_msg.reg_addr >= IN2_REG_ST)
      && (md_data_msg.reg_addr + md_data_msg.data_len <= IN2_REG_END))
	{
		p_reg = input_reg2_buf;
		start_addr = md_data_msg.reg_addr - IN2_REG_ST;
	}
	if((md_data_msg.reg_addr >= IN3_REG_ST)
      && (md_data_msg.reg_addr + md_data_msg.data_len <= IN3_REG_END))
	{
		p_reg = input_reg3_buf;
		start_addr = md_data_msg.reg_addr - IN3_REG_ST;
	}	
	if((md_data_msg.reg_addr >= IN4_REG_ST)
      && (md_data_msg.reg_addr + md_data_msg.data_len <= IN4_REG_END))
	{
		p_reg = input_reg4_buf;
		start_addr = md_data_msg.reg_addr - IN4_REG_ST;
	}	
	if((md_data_msg.reg_addr >= IN5_REG_ST)
      && (md_data_msg.reg_addr + md_data_msg.data_len <= IN5_REG_END))
	{
		p_reg = input_reg5_buf;
		start_addr = md_data_msg.reg_addr - IN5_REG_ST;
	}
	if((md_data_msg.reg_addr >= IN6_REG_ST)
      && (md_data_msg.reg_addr + md_data_msg.data_len <= IN6_REG_END))
	{
		p_reg = input_reg6_buf;
		start_addr = md_data_msg.reg_addr - IN6_REG_ST;
	}
	if((md_data_msg.reg_addr >= IN7_REG_ST)
      && (md_data_msg.reg_addr + md_data_msg.data_len <= IN7_REG_END))
	{
		p_reg = input_reg7_buf;
		start_addr = md_data_msg.reg_addr - IN7_REG_ST;
	}
	else
	{
		
	}
	
    for (i = 0; i < md_data_msg.data_len; ++i) 
	{
        p_tx[idx_cnt ++] = p_reg[i + start_addr] >> 8;
		p_tx[idx_cnt ++] = p_reg[i + start_addr];
    }

    crc_code = modbus_calc_crc(tx_buf, idx_cnt);

    p_tx[idx_cnt ++] = crc_code & 0xff;
    p_tx[idx_cnt ++] = crc_code >> 8;

    *tx_len = idx_cnt;   //修改
}


static void huawei_read_hold_reg_reply(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len)
{
	uint16_t data_len = 0;
    uint16_t crc_code = 0;
    uint8_t *p_tx = tx_buf;
	
    *p_tx ++ = md_data_msg.addr;
    *p_tx ++ = md_data_msg.cmd_code;
	*p_tx ++ = md_data_msg.reg_addr >> 8;
	*p_tx ++ = md_data_msg.reg_addr & 0xff;
    *p_tx ++ = md_data_msg.data_len >> 8; 
    *p_tx ++ = md_data_msg.data_len & 0xff; 

    crc_code = modbus_calc_crc(tx_buf , 6);

    *p_tx ++ = crc_code;
    *p_tx ++ = crc_code >> 8;

    *tx_len = (data_len + 8);
}


static void huawei_update_in1_reg(void)
{
	uint8_t i = 0;
	uint8_t cell_num = 0;
	uint8_t sys_state = 0;
	uint32_t cap_val = 0;
	uint8_t soh = 0;
    input_reg1_buf[0] = master_data_reg.avg_batt_volt;
    input_reg1_buf[1] = master_data_reg.avg_batt_volt;
    input_reg1_buf[2] = master_data_reg.total_bus_curr;
    input_reg1_buf[3] =  master_data_reg.avg_soc;
	soh = master_data_reg.avg_soh;
	if(soh > 100)
		soh = 100;
    input_reg1_buf[4] = soh; 
    input_reg1_buf[5] = (var_get_data(VAR_ID_TP_MAXT_VAL) - 2731) * 0.1;
    input_reg1_buf[6] = (var_get_data(VAR_ID_TP_MINT_VAL) - 2731) * 0.1;
	
	cap_val = master_data_reg.total_full_cap;
	if(cap_val >= MAX_DISP_CAP)
		cap_val = MAX_DISP_CAP;
	
    input_reg1_buf[8] = cap_val;
	
//	for( i = 0x07; i < 0x0E; ++ i)
//	{
//		input_reg1_buf[i] = 0;
//	}
	input_reg1_buf[0x0A] = 0x01;
	input_reg1_buf[0x0C] = 0x02;
	input_reg1_buf[0x0D] = 0x05;	
	if(master_data_reg.total_bus_curr > 0)
    sys_state = 0x02;
	else if(master_data_reg.total_bus_curr < 0)
	sys_state = 0x03;
	else 
	sys_state = 0x04;	
	input_reg1_buf[0x0E] = sys_state;	
	
	for( i = 0x0F; i < 0x12; ++ i)
	{
		input_reg1_buf[i] = 0;
	}	
	
	for( i = 0;i < CFG_TEMP_NUM; ++ i)
	{
		input_reg1_buf[0x12 + i] = (var_get_data(VAR_ID_CELL_TEMP01 + i) - 500) * 0.1 + 0.5;
	}
	for( ;i < 16; ++ i)
	{
		input_reg1_buf[0x12 + i] = 0xFC19;
	}
	
	cell_num = param_get_data(PAR_ID_CB_CELL_NUM);
	for( i = 0;(i < cell_num) && ( i < 16); ++ i)
	{
		input_reg1_buf[0x22 + i] = var_get_data(VAR_ID_CELL_VOLT01 + i);
	}
	
	for( ;i < 16; ++ i)
	{
		input_reg1_buf[0x22 + i] = 0xFFFF;
	}
	
	for(i = 0; i <= 16; ++ i)
	{
		input_reg1_buf[0x32 + i] = 0;
	}
	//input_reg1_buf[0x46] = 0;
	
}

static void huawei_update_in2_reg(void)
{
    input_reg2_buf[0] = (SOFT_VER_MAIN << 8) + SOFT_VER_RELEASE;
    input_reg2_buf[1] = 0x30 + var_get_data(VAR_ID_HARD_VER);//硬件版本
    input_reg2_buf[2] = 0x30 + putchar(boot_param_read_par(BP_ID_BOOT_VER));
    input_reg2_buf[3] = 0x01; //BMS 和锂电池一体。
	input_reg2_buf[4] = 0x00; // 表示华为
	input_reg2_buf[5] = 0x00CB; //子软件
	input_reg2_buf[6] = param_get_data(PAR_ID_STD_CAP) * 0.01;
	input_reg2_buf[7] = 0x4857; //HW
	input_reg2_buf[8] = 0x2020;
	input_reg2_buf[9] = 0xE130;
	input_reg2_buf[0x0A] = 0x8594;	
	input_reg2_buf[0x0B] = 0x381F;
    input_reg2_buf[0x0C] = 0x0044; 	
	input_reg2_buf[0x0D] = 0; 
	input_reg2_buf[0x0E] = param_get_data(PAR_ID_CB_CELL_NUM);
	input_reg2_buf[0x0F] = 0; 
    input_reg2_buf[0x10] = 0x01;
    input_reg2_buf[0x11] = 0x01;
    input_reg2_buf[0x12] = 0x0A;
    input_reg2_buf[0x13] = 0x2588;
    input_reg2_buf[0x14] = 0x3231;
    input_reg2_buf[0x15] = 0x007A;

 	
}

static void huawei_update_in3_reg(void)
{
	float sys_curr = 0;
    input_reg3_buf[0] =	0;
    input_reg3_buf[1] =	0;
    input_reg3_buf[2] =	0;
    input_reg3_buf[3] =	0;	
	sys_curr = master_data_reg.total_bus_curr * 0.01;
	if(sys_curr < 0)
		sys_curr = -sys_curr;
	input_reg3_buf[4] = master_data_reg.avg_batt_volt *0.01 * sys_curr;
	input_reg3_buf[5] = master_data_reg.avg_batt_volt;	
	input_reg3_buf[6] = master_data_reg.total_bus_curr * 0.01;
	input_reg3_buf[7] = 0;
	input_reg3_buf[8] = 0x01;
	input_reg3_buf[9] = 0; //累计运行时间
	input_reg3_buf[0x0A] = 0; //累计运行时间
}

static void huawei_update_in4_reg(void)
{
    uint8_t i = 0;
	float sys_curr = 0;	
	uint16_t sys_wh_temp = 0;

    param_get_multi_data(PAR_ID_BMS_CODE , 8 , &input_reg4_buf[0]);		
	for( i = 0;i < 11; ++ i)
	{
	input_reg4_buf[i] = 0xFF;
	}	
	
	input_reg4_buf[0x0B] = 0x0018;
	input_reg4_buf[0x0C] = 0xAAB0;
    input_reg4_buf[0x0E] = 0x00E4;
	sys_curr = master_data_reg.total_bus_curr * 0.01;
	if(sys_curr < 0)
		sys_curr = -sys_curr;
	sys_wh_temp = master_data_reg.avg_batt_volt *0.01 * sys_curr;	
    input_reg4_buf[0x0F] = sys_wh_temp;	//上报电池瓦时
    input_reg4_buf[0x10] = sys_wh_temp >> 8 ;	//上报电池瓦时	
	
	
}

static void huawei_update_in5_reg(void)
{
	uint8_t i = 0;
	rtc_data_type rtc_time = {0};
	
	If_rtc_read_time(&rtc_time);
	
    input_reg5_buf[0] = rtc_time.year;
	input_reg5_buf[1] = rtc_time.month;
	input_reg5_buf[2] = rtc_time.day;
	input_reg5_buf[3] = rtc_time.hour;
	input_reg5_buf[4] = rtc_time.min;
	input_reg5_buf[5] = rtc_time.sec;
	
	input_reg5_buf[8] = 0x0048; 
	input_reg5_buf[9] = 0xFFFF;
	input_reg5_buf[0x0A] = 0X01EB;
	input_reg5_buf[0x0B] = 0X02A8;
	input_reg5_buf[0x0C] = 0X021C;
	input_reg5_buf[0x0D] = 0X00D2;	
	input_reg5_buf[0x0E] = 0X01DB;	
	input_reg5_buf[0x18] = 0X0055;	
	
	for(i = 0; i <= 16; ++ i)
	{
		input_reg1_buf[0x100 + i] = 0;
	}
}

static void huawei_update_in6_reg(void)
{
    input_reg6_buf[0] = 5029;
	input_reg6_buf[1] = 50;
	input_reg6_buf[2] = 0xFFFF;
	
}

static void huawei_update_in7_reg(void)
{
    uint8_t i = 0;
	
	for( i = 0;i < 16; ++ i)
	{
		input_reg7_buf[i] = 60 + i;
	}

}

static uint16_t huawei_write_reg(md_data_type md_data_msg)
{
	uint16_t state = 0;
	rtc_data_type rtc_time = {0};
	
	rtc_time.year = md_data_msg.data_buf[0];
	rtc_time.month = md_data_msg.data_buf[1];
	rtc_time.day = md_data_msg.data_buf[2];

	rtc_time.hour = md_data_msg.data_buf[3];
	rtc_time.min = md_data_msg.data_buf[4];
	rtc_time.sec = md_data_msg.data_buf[5];
	
	If_rtc_set_time(rtc_time);
	
	return state;
}
/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
